using System;
using System.Collections.Generic;
using System.Text;
using MacomberMap.Common.Components;
using MacomberMap.Common.Internals;
using System.Reflection;

namespace MacomberMap.Loader.User_Events
{
    /// <summary>
    /// This structure holds the information on a user action (e.g., moving a substation, creating a new sub, etc.)
    /// </summary>
    public class MM_Action
    {
        #region Variable declaration
        /// <summary>The element that's been modified</summary>
        public MM_Element ModifiedElement;

        /// <summary>The name of the property</summary>
        public String PropertyName;

        /// <summary>The old value for the item</summary>
        public Object OldValue;

        /// <summary>The new value for the item</summary>
        public Object NewValue;
        #endregion

        #region Initialization
        /// <summary>
        /// Create a new map change event, and assign it
        /// </summary>
        /// <param name="ModifiedElement">The modified element</param>
        /// <param name="PropertyName">The property name affected by the action</param>
        /// <param name="OldValue">The old value</param>
        /// <param name="NewValue">Our new value</param>
        public MM_Action(MM_Element ModifiedElement, String PropertyName, Object OldValue, Object NewValue)
        {
            this.ModifiedElement = ModifiedElement;
            this.PropertyName = PropertyName;
            this.OldValue = OldValue;
            this.NewValue = NewValue;
            AssignNewValue();

        }
        #endregion

        #region Value assignment
        /// <summary>
        /// Assign the specified property with the parsed value
        /// </summary>
        public void AssignNewValue()
        {
            if (PropertyName == "Add")
            {
                if (ModifiedElement is MM_Substation)
                    MM_Repository.Substations.Add(ModifiedElement.Name, ModifiedElement as MM_Substation);
                else if (ModifiedElement is MM_Line)
                    MM_Repository.Lines.Add(ModifiedElement.Name, ModifiedElement as MM_Line);
                MM_Repository.TEIDs.Add(ModifiedElement.TEID, ModifiedElement);
            }
            else if (PropertyName == "Remove")
            {
                if (ModifiedElement is MM_Substation)
                    MM_Repository.Substations.Remove(ModifiedElement.Name);
                else if (ModifiedElement is MM_Line)
                    MM_Repository.Lines.Remove(ModifiedElement.Name);
                MM_Repository.TEIDs.Remove(ModifiedElement.TEID);
            }
            else
            {
                PropertyInfo pI = ModifiedElement.GetType().GetProperty(PropertyName);
                if (pI != null)
                    pI.SetValue(ModifiedElement, NewValue, null);
                else
                {
                    FieldInfo fI = ModifiedElement.GetType().GetField(PropertyName);
                    if (fI != null)
                        fI.SetValue(ModifiedElement, NewValue);
                    else
                        throw new InvalidOperationException("Unable to find field/property named " + PropertyName);
                }
            }
        }

        /// <summary>
        /// Assign the specified property with the parsed value
        /// </summary>
        /// <param name="NewValue">The new value to be assigned and implemented</param>
        public void AssignNewValue(Object NewValue)
        {
            this.NewValue = NewValue;
            PropertyInfo pI = ModifiedElement.GetType().GetProperty(PropertyName);
            if (pI != null)
                pI.SetValue(ModifiedElement, NewValue, null);
            else
            {
                FieldInfo fI = ModifiedElement.GetType().GetField(PropertyName);
                if (fI != null)
                    fI.SetValue(ModifiedElement, NewValue);
                else
                    throw new InvalidOperationException("Unable to find field/property named " + PropertyName);
            }
        }

        /// <summary>
        /// Assign the specified property with the parsed value
        /// </summary>
        public void AssignOldValue()
        {
            if (PropertyName == "Add")
            {
                if (ModifiedElement is MM_Substation)
                    MM_Repository.Substations.Remove(ModifiedElement.Name);
                else if (ModifiedElement is MM_Line)
                    MM_Repository.Lines.Remove(ModifiedElement.Name);
                MM_Repository.TEIDs.Remove(ModifiedElement.TEID);
            }
            else if (PropertyName == "Remove")
            {
                if (ModifiedElement is MM_Substation)
                    MM_Repository.Substations.Add(ModifiedElement.Name, ModifiedElement as MM_Substation);
                else if (ModifiedElement is MM_Line)
                    MM_Repository.Lines.Add(ModifiedElement.Name, ModifiedElement as MM_Line);
                MM_Repository.TEIDs.Add(ModifiedElement.TEID, ModifiedElement);
            }
            else
                ModifiedElement.GetType().GetProperty(PropertyName).SetValue(ModifiedElement, OldValue, null);
        }
        #endregion

    }
}